package com.tian.es.service.impl;

import com.tian.common.CommonResult;
import com.tian.dto.ChargeStationLocationReqDto;
import com.tian.dto.StationInfoIndexRespDto;
import com.tian.entity.StationInfo;
import com.tian.es.entity.ChargeStationLocation;
import com.tian.es.entity.GeoLocationPoiVo;
import com.tian.es.entity.NearByPoiParam;
import com.tian.es.service.ChargeStationEsService;
import com.tian.mapper.ChargeStationInfoMapper;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * {@code @description:} 站点数据存放到ES中
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-07-23 18:46
 * {@code @version:} 1.0
 */
@Service
public class ChargeStationEsServiceImpl implements ChargeStationEsService {

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Resource
    private ChargeStationInfoMapper chargeStationInfoMapper;

    @Override
    public void createIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(ChargeStationLocation.class);
        indexOperations.create();
        Document mapping = indexOperations.createMapping();
        indexOperations.putMapping(mapping);
    }

    @Override
    public void add(ChargeStationLocation chargeStationLocation) {
        elasticsearchRestTemplate.save(chargeStationLocation);
    }

    @Override
    public void delete(Integer id) {
        elasticsearchRestTemplate.delete(id.toString(), ChargeStationLocation.class);
    }

    @Override
    public CommonResult<List<StationInfoIndexRespDto>> getNearByLocation(NearByPoiParam nearByPoiParam) {

        List<StationInfoIndexRespDto> stationInfoIndexRespDtoList = new ArrayList<>();

        List<GeoLocationPoiVo> geoLocationPoiVoList = new ArrayList<>();
        Pageable pageable = PageRequest.of(0, nearByPoiParam.getSize());

        // 搜索字段为 location
        GeoDistanceQueryBuilder geoBuilder = new GeoDistanceQueryBuilder("geoPoint");
        //指定从哪个位置搜索
        geoBuilder.point(nearByPoiParam.getLat(), nearByPoiParam.getLon());
        //指定搜索多少km
        geoBuilder.distance(nearByPoiParam.getDistance(), DistanceUnit.KILOMETERS);

        // 距离排序
        GeoDistanceSortBuilder sortBuilder = new GeoDistanceSortBuilder("geoPoint", nearByPoiParam.getLat(), nearByPoiParam.getLon());
        //升序
        sortBuilder.order(SortOrder.ASC);
        //搜索
        SearchHits<ChargeStationLocation> searchHits = elasticsearchRestTemplate
                .search(new NativeSearchQueryBuilder()
                        .withPageable(pageable)
                        .withFilter(geoBuilder)
                        .withSort(sortBuilder)
                        .build(), ChargeStationLocation.class);
        //获取充电站信息数据
        searchHits.forEach(searchHit -> {
            double calculate = GeoDistance.PLANE.calculate(searchHit.getContent().getGeoPoint().getLat(), searchHit.getContent().getGeoPoint().getLon(), nearByPoiParam.getLat(), nearByPoiParam.getLon(), DistanceUnit.METERS);
            GeoLocationPoiVo geoLocationPoiVo = new GeoLocationPoiVo();
            BeanUtils.copyProperties(searchHit.getContent(), geoLocationPoiVo);
            geoLocationPoiVo.setSpecificDistance(calculate + "米");
            geoLocationPoiVoList.add(geoLocationPoiVo);
        });
        List<Integer> idList = new ArrayList<>();
        geoLocationPoiVoList.forEach(geoLocationPoiVo -> {
            idList.add(Integer.parseInt(geoLocationPoiVo.getId()));
        });

        List<StationInfo> stationInfos = chargeStationInfoMapper.selectByIdList(idList);
        stationInfos.forEach(stationInfo -> {
            StationInfoIndexRespDto stationInfoIndexRespDto = new StationInfoIndexRespDto();
            // TODO: 2024-07-23 属性赋值以及属性转换
            BeanUtils.copyProperties(stationInfo, stationInfoIndexRespDto);
            stationInfoIndexRespDtoList.add(stationInfoIndexRespDto);
        });

        //站点信息中使用中的充电枪个数需要统计--设备状态

        return CommonResult.success(stationInfoIndexRespDtoList);
    }
}
